package fsm

import (
	"fmt"
	"sync"
)

const (
	_NOT_FOUND_STATE                         = "fsm: no found state '%s'"
	_NOT_FOUND_TRANSITION_IN_STATE           = "fsm: not found transition handler in state '%s'"
	_NOT_FOUND_TRANSITION_IN_STATE_VIA_EVENT = "fsm: not found transition handler in state '%s' via event '%s'"

	_FAILED_TO_HANDLE_EVENT = "fsm: failed to handle event '%s': %v"
	_FAILED_TO_EXIT_STATE   = "fsm: failed to exit state '%s': %v"
	_FAILED_TO_ENTER_STATE  = "fsm: failed to enter state '%s': %v"

	_UNDEFINED_INITIAL_STATE                          = "fsm: undefined initial state '%s'"
	_UNDEFINED_SOURCE_STATE                           = "fsm: undefined source state '%s'"
	_UNDEFINED_DESTINATION_STATE_FROM_STATE_VIA_EVENT = "fsm: undefined destination state '%s' for transition from state '%s' via event '%s'"
)

type (
	// State 定义状态的数据类型
	State string

	// Event 定义事件的数据类型
	Event string

	// TransitHandler 定义状态转移时执行的回调函数类型
	TransitHandler func(from State, to State, data map[Event]any) error

	// StateCallbackHandler 定义进入或离开状态时执行的回调函数类型
	StateCallbackHandler func(state State, data map[Event]any) error
)

// FSM 定义有限状态机的数据结构
type FSM struct {
	// states 状态集
	states map[State]struct{}
	// transitions 状态A->事件->状态B
	transitions map[State]map[Event]State
	// eventHandlers 触发某事件时的处理器
	eventHandlers map[Event][]TransitHandler
	// exitHandlers 退出某状态时的处理器
	exitHandlers map[State][]StateCallbackHandler
	// enterHandlers 进入某状态时的处理器
	enterHandlers map[State][]StateCallbackHandler

	lock sync.RWMutex
}

// New 创建一个新的有限状态机实例
func New() *FSM {
	return &FSM{
		states:        make(map[State]struct{}),
		transitions:   make(map[State]map[Event]State),
		enterHandlers: make(map[State][]StateCallbackHandler),
		exitHandlers:  make(map[State][]StateCallbackHandler),
		eventHandlers: make(map[Event][]TransitHandler),
	}
}

// AddState 添加一个新状态
func (own *FSM) AddState(states ...State) {
	own.lock.Lock()
	for _, state := range states {
		own.states[state] = struct{}{}
	}
	own.lock.Unlock()
}

// AddTransition 添加一个状态转移规则
func (own *FSM) AddTransition(from State, event Event, to State) error {
	own.lock.Lock()
	defer own.lock.Unlock()

	// 检查状态是否存在
	if _, isExisted := own.states[from]; !isExisted {
		return fmt.Errorf(_NOT_FOUND_STATE, from)
	}
	if _, isExisted := own.states[to]; !isExisted {
		return fmt.Errorf(_NOT_FOUND_STATE, to)
	}

	// 初始化源状态的转移映射（若尚未初始化）
	if own.transitions[from] == nil {
		own.transitions[from] = make(map[Event]State)
	}

	// 添加转移规则
	own.transitions[from][event] = to
	return nil
}

// CallOnEnter 添加进入状态时的回调函数
func (own *FSM) CallOnEnter(state State, handlers ...StateCallbackHandler) error {
	own.lock.Lock()
	defer own.lock.Unlock()

	if _, isExisted := own.states[state]; !isExisted {
		return fmt.Errorf(_NOT_FOUND_STATE, state)
	}

	for _, handler := range handlers {
		if handler != nil {
			own.enterHandlers[state] = append(own.enterHandlers[state], handler)
		}
	}

	return nil
}

// CallOnExit 添加退出状态时的回调函数
func (own *FSM) CallOnExit(state State, handlers ...StateCallbackHandler) error {
	own.lock.Lock()
	defer own.lock.Unlock()

	if _, isExisted := own.states[state]; !isExisted {
		return fmt.Errorf(_NOT_FOUND_STATE, state)
	}

	for _, handler := range handlers {
		if handler != nil {
			own.exitHandlers[state] = append(own.exitHandlers[state], handler)
		}
	}

	return nil
}

// CallOnEvent 添加处理事件时的回调函数
func (own *FSM) CallOnEvent(event Event, handlers ...TransitHandler) {
	own.lock.Lock()
	for _, handler := range handlers {
		if handler != nil {
			own.eventHandlers[event] = append(own.eventHandlers[event], handler)
		}
	}
	own.lock.Unlock()
}

// Trigger 触发状态转移事件
func (own *FSM) Trigger(current State, event Event, data map[Event]any) (State, error) {
	own.lock.Lock()
	defer own.lock.Unlock()

	// 检查是否存在从当前状态出发的此事件转移
	stateTransitions, isExisted := own.transitions[current]
	if !isExisted {
		return "", fmt.Errorf(_NOT_FOUND_TRANSITION_IN_STATE, current)
	}

	dstState, isExisted := stateTransitions[event]
	if !isExisted {
		return "", fmt.Errorf(_NOT_FOUND_TRANSITION_IN_STATE_VIA_EVENT, current, event)
	}

	// 触发事件时调用
	if handlers, ok := own.eventHandlers[event]; ok {
		for _, handler := range handlers {
			if err := handler(current, dstState, data); err != nil {
				return "", fmt.Errorf(_FAILED_TO_HANDLE_EVENT, event, err)
			}
		}
	}

	// 退出当前状态时调用
	if handlers, ok := own.exitHandlers[current]; ok {
		for _, handler := range handlers {
			if err := handler(current, data); err != nil {
				return "", fmt.Errorf(_FAILED_TO_EXIT_STATE, current, err)
			}
		}
	}

	// 进入目标状态时调用
	if handlers, ok := own.enterHandlers[dstState]; ok {
		for _, handler := range handlers {
			if err := handler(dstState, data); err != nil {
				return "", fmt.Errorf(_FAILED_TO_ENTER_STATE, dstState, err)
			}
		}
	}

	return dstState, nil
}

// GetTransitions 返回从指定状态出发的所有转移
func (own *FSM) GetTransitions(state State) (map[Event]State, error) {
	own.lock.RLock()
	defer own.lock.RUnlock()

	if _, isExisted := own.states[state]; !isExisted {
		return nil, fmt.Errorf(_NOT_FOUND_STATE, state)
	}

	// 创建转移映射的副本以防止外部修改
	states := make(map[Event]State)
	for event, toState := range own.transitions[state] {
		states[event] = toState
	}

	return states, nil
}

// Validate 验证状态机配置是否有效
func (own *FSM) Validate(state State) error {
	own.lock.RLock()
	defer own.lock.RUnlock()

	// 检查当前状态是否有效
	if _, isExisted := own.states[state]; !isExisted {
		return fmt.Errorf(_UNDEFINED_INITIAL_STATE, state)
	}

	// 检查所有转移是否指向有效状态
	for fromState, eventMap := range own.transitions {
		if _, isExisted := own.states[fromState]; !isExisted {
			return fmt.Errorf(_UNDEFINED_SOURCE_STATE, fromState)
		}

		for event, toState := range eventMap {
			if _, isExisted := own.states[toState]; !isExisted {
				return fmt.Errorf(_UNDEFINED_DESTINATION_STATE_FROM_STATE_VIA_EVENT, fromState, event, toState)
			}
		}
	}

	return nil
}
